package tech.xs.sys.service.impl;

import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import tech.xs.common.domain.enums.YesNoEnum;
import tech.xs.common.framework.domain.constant.Symbol;
import tech.xs.common.framework.service.CrudServiceImpl;
import tech.xs.common.framework.util.PermissionUtil;
import tech.xs.common.framework.util.RoleUtil;
import tech.xs.common.sys.domain.constant.SysCacheKeyConstant;
import tech.xs.sys.dao.SysRolePermissionDao;
import tech.xs.sys.domain.entity.SysPermission;
import tech.xs.sys.domain.entity.SysRole;
import tech.xs.sys.domain.entity.SysRolePermission;
import tech.xs.sys.service.SysRolePermissionService;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class SysRolePermissionServiceImpl extends CrudServiceImpl<SysRolePermissionDao, SysRolePermission> implements SysRolePermissionService {


    @Resource
    private RedissonClient redissonClient;
    @Resource
    private SysRolePermissionDao sysRolePermissionDao;

    public Set<String> loadEnableRolePermission(Set<String> roles) {
        if (roles == null || roles.isEmpty()) {
            return new HashSet<>();
        }
        String cacheKey = SysCacheKeyConstant.SYS_ENABLE_PERMISSION_CACHE + RoleUtil.getRolesHashCode(roles);
        RLock lock = PermissionUtil.getEnableRolePermissionCacheWriteLock();
        try {
            RBucket<Set<String>> bucket = redissonClient.getBucket(cacheKey);
            List<SysRolePermission> sysRolePermissions = sysRolePermissionDao.selectJoinList(SysRolePermission.class, new MPJLambdaWrapper<SysRolePermission>().selectAll(SysRolePermission.class)
                    .leftJoin(SysPermission.class, SysPermission::getCode, SysRolePermission::getPermissionCode)
                    .leftJoin(SysRole.class, SysRole::getCode, SysRolePermission::getRoleCode)
                    .in(SysRolePermission::getRoleCode, roles)
                    .eq(SysPermission::getPermissionStatus, YesNoEnum.YES)
                    .eq(SysRole::getRoleStatus, YesNoEnum.YES)
                    .orderByAsc(SysRolePermission::getPermissionCode));
            Set<String> permissions = new HashSet<>();
            for (SysRolePermission item : sysRolePermissions) {
                permissions.add(item.getPermissionCode());
            }
            bucket.set(permissions);
            return permissions;
        } catch (Exception e) {
            log.error("获取启用角色权限失败[缓存不存在]", e);
            throw e;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public void deleteEnableRolePermissionCache() {
        RLock lock = PermissionUtil.getEnableRolePermissionCacheWriteLock();
        try {
            redissonClient.getKeys().deleteByPattern(SysCacheKeyConstant.SYS_ENABLE_PERMISSION_CACHE + Symbol.ASTERISK);
        } catch (Exception e) {
            log.error("删除启用角色权限失败", e);
            throw e;
        } finally {
            lock.unlock();
        }
    }


}
